// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//
//  Project:   Talina Gaming System (TgS) (∂)
//  File:      TgS (W32) Common - Math API [Vector] [M] [U32].inl
//  Author:    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
//  Version:   4.0
//
// ------------------------------------------------------------------------------------------------------------------------------ //
//
//  Copyright: © 2002-2010, Andrew Aye.  All Rights Reserved.
//
//  This software is free for non-commercial use. Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met: 
//    Redistributions of source code must retain this copyright notice, this list of conditions and the following disclaimers. 
//    Redistributions in binary form must reproduce this copyright notice, this list of conditions and the following
//      disclaimers in the documentation and other materials provided with the distribution. 
//
//  Neither the names of the copyright owner nor the names of its contributors may be used to endorse or promote products derived
//  from this software without specific prior written permission. 
//
//  The intellectual property rights of the algorithms used reside with Andrew Aye.  You may not use this software, in whole or
//  in part, in support of any commercial product without the express written consent of the author.
//
//  There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
#if !defined(_TGS_W32_COMMON_MATH_API_VECTOR_U32_INL_)
#define _TGS_W32_COMMON_MATH_API_VECTOR_U32_INL_
#pragma once

// START TGS - MATH ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
// Vector [M]
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

// SIMD - LOAD/SET OPERATIONS --------------------------------------------------------------------------------------------------- //

TgINLINE TgVEC_M_U32_04 M_SET4_U32_04( C_TgUINT32 fX, C_TgUINT32 fY, C_TgUINT32 fZ, C_TgUINT32 fW )
{
    return (( _mm_set_epi32( fW, fZ, fY, fX ) ));
};


TgINLINE TgVEC_M_U32_04 M_SETU_U32_04( CPCU_TgUINT32 puiVal )
{
    return (( _mm_loadu_si128( (__m128i*)puiVal ) ));
};


TgINLINE TgVEC_M_U32_04 M_SETA_U32_04( CPCU_TgUINT32 puiVal )
{
    return (( _mm_load_si128( (__m128i*)puiVal ) ));
};


TgINLINE TgVEC_M_U32_04 M_SET1_U32_04( C_TgUINT32 uiVal )
{
    return (( _mm_set1_epi32( uiVal ) ));
};




// SIMD - PERMUTE AND SELECT ---------------------------------------------------------------------------------------------------- //

TgINLINE TgVEC_M_U32_04 M_PERM_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight, C_TgVEC_M_U32_04 tuvMask )
{
    __m128i                             vX = { 0 };
    TgUINT32                            uiIndex;

    for (uiIndex = 0; uiIndex < 4; ++uiIndex)
    {
        C_TgUINT32                          byMask = tuvMask.m128i_u32[uiIndex] & 0x1F;
        C_TgUINT32                          ui0 = tvLeft.m128i_u32[byMask & 0xF];
        C_TgUINT32                          ui1 = tvRight.m128i_u32[byMask & 0xF];

        vX.m128i_u32[uiIndex] = 0 == (byMask & 0x10) ? ui0 : ui1;
    };

    return (( vX ));
};


TgINLINE TgVEC_M_U32_04 M_SEL_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight, C_TgVEC_M_U32_04 tuvMask )
{
    return ((
        _mm_or_si128(
            _mm_and_si128( tvLeft, _mm_xor_si128( TgKV_FFFF.m_u32_v04.m_mData, tuvMask ) ),
            _mm_and_si128( tvRight, tuvMask )
        )
    ));
};




// SIMD - LOGICAL --------------------------------------------------------------------------------------------------------------- //

TgINLINE TgVEC_M_U32_04 M_AND_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (( _mm_and_si128( tvLeft, tvRight ) ));
};


TgINLINE TgVEC_M_U32_04 M_OR_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (( _mm_or_si128( tvLeft, tvRight ) ));
};


TgINLINE TgVEC_M_U32_04 M_XOR_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (( _mm_xor_si128( tvLeft, tvRight ) ));
};




// SIMD - BOUNDS ---------------------------------------------------------------------------------------------------------------- //

TgINLINE TgVEC_M_U32_04 M_MAX_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (( _mm_max_epu32( tvLeft, tvRight ) ));
};


TgINLINE TgVEC_M_U32_04 M_MIN_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (( _mm_min_epu32( tvLeft, tvRight ) ));
};




// SIMD - COMPARISON OPERATORS -------------------------------------------------------------------------------------------------- //

TgINLINE TgVEC_M_U32_04 M_CMP_EQ_M_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (( _mm_cmpeq_epi32( tvLeft, tvRight ) ));
};


TgINLINE TgVEC_M_U32_04 M_CMP_NE_M_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return ((
        _mm_xor_si128( TgKV_FFFF.m_u32_v04.m_mData, _mm_cmpeq_epi32( tvLeft, tvRight ) ) ));
};


TgINLINE TgVEC_M_U32_04 M_CMP_GE_M_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (( _mm_xor_si128( TgKV_FFFF.m_u32_v04.m_mData, M_CMP_GT_M_U32_04( tvRight, tvLeft ) ) ));
};


TgINLINE TgVEC_M_U32_04 M_CMP_GT_M_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    register __m128i                    vX1;

    vX1.m128i_u32[0] = tvLeft.m128i_u32[0] > tvRight.m128i_u32[0] ? 0xFFFFFFFF : 0x00000000;
    vX1.m128i_u32[1] = tvLeft.m128i_u32[1] > tvRight.m128i_u32[1] ? 0xFFFFFFFF : 0x00000000;
    vX1.m128i_u32[2] = tvLeft.m128i_u32[2] > tvRight.m128i_u32[2] ? 0xFFFFFFFF : 0x00000000;
    vX1.m128i_u32[3] = tvLeft.m128i_u32[3] > tvRight.m128i_u32[3] ? 0xFFFFFFFF : 0x00000000;

    return (( vX1 ));
};


TgINLINE TgVEC_M_U32_04 M_CMP_LE_M_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (( _mm_xor_si128( TgKV_FFFF.m_u32_v04.m_mData, M_CMP_GT_M_U32_04( tvLeft, tvRight ) ) ));
};


TgINLINE TgVEC_M_U32_04 M_CMP_LT_M_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (M_CMP_GT_M_U32_04( tvRight, tvLeft ) );
};




// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //
// Vector [M] [I]
// -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. //

// SIMD - ARITHMETIC OPERATIONS ------------------------------------------------------------------------------------------------- //

TgINLINE TgVEC_M_U32_04 M_ADD_S_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (F_ADD_S_U32_04( (P_TgVEC_U32_04)&tvLeft, (P_TgVEC_U32_04)&tvRight ).m_mData);
};


TgINLINE TgVEC_M_U32_04 M_ADD_M_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (F_ADD_M_U32_04( (P_TgVEC_U32_04)&tvLeft, (P_TgVEC_U32_04)&tvRight ).m_mData);
};


TgINLINE TgVEC_M_U32_04 M_SUB_S_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (F_SUB_S_U32_04( (P_TgVEC_U32_04)&tvLeft,(P_TgVEC_U32_04) &tvRight ).m_mData);
};


TgINLINE TgVEC_M_U32_04 M_SUB_M_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (F_SUB_M_U32_04( (P_TgVEC_U32_04)&tvLeft, (P_TgVEC_U32_04)&tvRight ).m_mData);
};


TgINLINE TgVEC_M_U32_04 M_AVG_U32_04( C_TgVEC_M_U32_04 tvLeft, C_TgVEC_M_U32_04 tvRight )
{
    return (F_AVG_U32_04( (P_TgVEC_U32_04)&tvLeft, (P_TgVEC_U32_04)&tvRight ).m_mData);
};


#endif //  END  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////